﻿using System;
using gbL.NetBoard.Broadcast;

namespace gbL.NetBoard.Helpers
{
    public abstract class MultiTypedMessageListener
    {
        public MultiTypedMessageListener() { }

        public MultiTypedMessageListener(Blackboard messages)
        {
            Attach(messages);
        }

        public void Attach(Blackboard messages)
        {
            if (Messages != null)
                DetachAndRemoveFilters(Messages);
            AttachAndFilter(messages);
        }

        void OnMessageAddedHandler(object sender, ChangedEventArgs e)
        {
            OnMessageAdded(e.Entry.Message);
        }

        void OnMessageRemovedHandler(object sender, ChangedEventArgs e)
        {
            OnMessageRemoved(e.Entry.Message);
        }

        protected virtual Blackboard Messages { get; set; }

        protected virtual void DetachAndRemoveFilters(Blackboard blackboard)
        {
            blackboard.Broadcaster.Added -= new EventHandler<ChangedEventArgs>(OnMessageAddedHandler);
            blackboard.Broadcaster.Removed -= new EventHandler<ChangedEventArgs>(OnMessageRemovedHandler);
            foreach (Type t in MessageTypes)
            {
                blackboard.Broadcaster.RemoveFilterAddedByType(this, t);
                blackboard.Broadcaster.RemoveFilterRemovedByType(this, t);
            }
        }

        protected virtual void AttachAndFilter(Blackboard blackboard)
        {
            blackboard.Broadcaster.Added += new EventHandler<ChangedEventArgs>(OnMessageAddedHandler);
            blackboard.Broadcaster.Removed += new EventHandler<ChangedEventArgs>(OnMessageRemovedHandler);
            foreach (Type t in MessageTypes)
            {
                blackboard.Broadcaster.FilterAddedByType(this, t);
                blackboard.Broadcaster.FilterRemovedByType(this, t);
            }
            Messages = blackboard;
        }

        protected abstract void OnMessageAdded(object message);

        protected abstract void OnMessageRemoved(object message);

        protected abstract Type[] MessageTypes { get; }
    }
}
